home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-04 / ms_sh21s.zip / SH210 / SRC / DIRECTOR.C next >
C/C++ Source or Header  |  1992-07-10  |  6KB  |  304 lines

  1. /*
  2.  * @(#)msd_dir.c 1.4 87/11/06    Public Domain.
  3.  *
  4.  *  A public domain implementation of BSD directory routines for
  5.  *  MS-DOS.  Written by Michael Rendell ({uunet,utai}michael@garfield),
  6.  *  August 1897
  7.  *
  8.  *  Modified by Ian Stewartson, Data Logic.
  9.  */
  10.  
  11. #include <sys/types.h>
  12. #include <sys/stat.h>
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <malloc.h>
  16. #include <string.h>
  17. #include <limits.h>
  18. #include <ctype.h>
  19. #include <errno.h>
  20. #include <dirent.h>
  21. #ifdef OS2
  22. #define INCL_DOSFILEMGR
  23. #include <os2.h>
  24. #else
  25. #include <dos.h>
  26. #endif
  27.  
  28. #ifdef OS2
  29. #  define ATTRIBUTES        (FILE_DIRECTORY | FILE_HIDDEN | FILE_SYSTEM | \
  30.                  FILE_NORMAL | FILE_READONLY | FILE_ARCHIVED)
  31. #else
  32. #  define ATTRIBUTES        (_A_SUBDIR | _A_HIDDEN | _A_SYSTEM | \
  33.                  _A_NORMAL | _A_RDONLY | _A_ARCH)
  34. #endif
  35.  
  36. typedef struct _dircontents    DIRCONT;
  37. static void            free_dircontents (DIRCONT *);
  38.  
  39. DIR        *opendir (name)
  40. const char    *name;
  41. {
  42.     struct stat        statb;
  43.     DIR            *dirp;
  44.     char        *last;
  45.     DIRCONT        *dp;
  46.     char        *nbuf;
  47. #ifdef OS2
  48.     FILEFINDBUF     dtabuf;
  49.     HDIR        d_handle = HDIR_SYSTEM;
  50.     USHORT        d_count = 1;
  51.     bool        HPFS = FALSE;
  52. #else
  53.     struct find_t    dtabuf;
  54. #endif
  55.     int            len = strlen (name);
  56.     
  57.     if (!len)
  58.     {
  59.     errno = ENOTDIR;
  60.     return (DIR *)NULL;
  61.     }
  62.  
  63.     if ((nbuf = malloc (len + 5)) == (char *)NULL)
  64.     return (DIR *) NULL;
  65.  
  66.     strcpy (nbuf, name);
  67.     last = &nbuf[len - 1];
  68.  
  69. /* Ok, DOS is very picky about its directory names.  The following are
  70.  * valid.
  71.  *
  72.  *  c:/
  73.  *  c:.
  74.  *  c:name/name1
  75.  *
  76.  *  c:name/ is not valid
  77.  */
  78.  
  79.     if (((*last == '\\') || (*last == '/')) && (len > 1) &&
  80.     (!((len == 3) && (name[1] == ':'))))
  81.     *(last--) = 0;
  82.  
  83. /* Check its a directory */    
  84.  
  85.     if (stat (nbuf, &statb) < 0)
  86.     {
  87.     free (nbuf);
  88.     return (DIR *) NULL;
  89.     }
  90.  
  91.     if (!S_ISDIR (statb.st_mode))
  92.     {
  93.     free (nbuf);
  94.     errno = ENOTDIR;
  95.     return (DIR *)NULL;
  96.     }
  97.  
  98.     if ((dirp = (DIR *) malloc (sizeof (DIR))) == (DIR *) NULL)
  99.     {
  100.     free (nbuf);
  101.     return (DIR *) NULL;
  102.     }
  103.  
  104. /* Set up to find everything */
  105.  
  106.     if ((*last != '\\') && (*last != '/'))
  107.     strcat (last, "/");
  108.  
  109.     strcat (last, "*.*");
  110.  
  111. /* For OS/2, find the file system type */
  112.  
  113. #ifdef OS2
  114.     HPFS = IsHPFSFileSystem (nbuf);
  115. #endif
  116.  
  117.     dirp->dd_loc      = 0;
  118.     dirp->dd_cp       = (DIRCONT *) NULL;
  119.     dirp->dd_contents = (DIRCONT *) NULL;
  120.  
  121. #ifdef OS2
  122.     if (DosFindFirst (nbuf, &d_handle, ATTRIBUTES, &dtabuf,
  123.               sizeof (FILEFINDBUF), &d_count, (ULONG)0) != 0)
  124. #else
  125.     if (_dos_findfirst (nbuf, ATTRIBUTES, &dtabuf) != 0)
  126. #endif
  127.     {
  128.     free (nbuf);
  129.     return dirp;
  130.     }
  131.  
  132.     do 
  133.     {
  134. #ifdef OS2
  135.     if (((dp = (DIRCONT *) malloc (sizeof (DIRCONT))) == (DIRCONT *)NULL) ||
  136.         ((dp->_d_entry = strdup (dtabuf.achName)) == (char *) NULL))
  137. #else
  138.     if (((dp = (DIRCONT *) malloc (sizeof (DIRCONT))) == (DIRCONT *)NULL) ||
  139.         ((dp->_d_entry = strdup (dtabuf.name)) == (char *) NULL))
  140. #endif
  141.     {
  142.         if (dp != (char *)NULL)
  143.         free ((char *)dp);
  144.  
  145.         free (nbuf);
  146.         free_dircontents (dirp->dd_contents);
  147. #ifdef OS2
  148.         DosFindClose (d_handle);
  149. #endif
  150.         return (DIR *) NULL;
  151.     }
  152.  
  153. #ifdef OS2
  154.     if (!HPFS)
  155.         strlwr (dp->_d_entry);
  156. #endif
  157.  
  158.     if (dirp->dd_contents != (DIRCONT *) NULL)
  159.         dirp->dd_cp = dirp->dd_cp->_d_next = dp;
  160.  
  161.     else
  162.         dirp->dd_contents = dirp->dd_cp = dp;
  163.  
  164.     dp->_d_next = (DIRCONT *) NULL;
  165.  
  166. #ifdef OS2
  167.     d_count = 1;
  168.     } while (DosFindNext (d_handle, &dtabuf, sizeof (FILEFINDBUF),
  169.               &d_count) == 0);
  170. #else
  171.     } while (_dos_findnext (&dtabuf) == 0);
  172. #endif
  173.  
  174.     dirp->dd_cp = dirp->dd_contents;
  175.     free (nbuf);
  176.  
  177. #ifdef OS2
  178.     DosFindClose (d_handle);
  179. #endif
  180.  
  181.     return dirp;
  182. }
  183.  
  184. int    closedir (dirp)
  185. DIR    *dirp;
  186. {
  187.     free_dircontents (dirp->dd_contents);
  188.     free ((char *)dirp);
  189.     return 0;
  190. }
  191.  
  192. struct dirent    *readdir (dirp)
  193. DIR        *dirp;
  194. {
  195.     static struct dirent    dp;
  196.     
  197.     if (dirp->dd_cp == (DIRCONT *) NULL)
  198.     return (struct dirent *) NULL;
  199.  
  200.     dp.d_reclen = strlen (strcpy (dp.d_name, dirp->dd_cp->_d_entry));
  201.     dp.d_off    = dirp->dd_loc * 32;
  202.     dp.d_ino    = (ino_t)++dirp->dd_loc;
  203.     dirp->dd_cp = dirp->dd_cp->_d_next;
  204. #ifndef OS2
  205.     strlwr (dp.d_name);
  206. #endif
  207.  
  208.     return &dp;
  209. }
  210.  
  211. void    rewinddir (dirp)
  212. DIR    *dirp;
  213. {
  214.     seekdir (dirp, (off_t)0);
  215. }
  216.  
  217. void    seekdir (dirp, off)
  218. DIR    *dirp;
  219. off_t    off;
  220. {
  221.     long    i = off;
  222.     DIRCONT    *dp;
  223.  
  224.     if (off < 0L)
  225.     return;
  226.  
  227.     for (dp = dirp->dd_contents; (--i >= 0) && (dp != (DIRCONT *)NULL);
  228.      dp = dp->_d_next)
  229.     ;
  230.  
  231.     dirp->dd_loc = off - (i + 1);
  232.     dirp->dd_cp = dp;
  233. }
  234.  
  235. off_t    telldir(dirp)
  236. DIR    *dirp;
  237. {
  238.     return dirp->dd_loc;
  239. }
  240.  
  241. static void    free_dircontents (dp)
  242. DIRCONT        *dp;
  243. {
  244.     DIRCONT    *odp;
  245.  
  246.     while ((odp = dp) != (DIRCONT *)NULL) 
  247.     {
  248.     if (dp->_d_entry != (char *)NULL)
  249.         free (dp->_d_entry);
  250.  
  251.     dp = dp->_d_next;
  252.     free ((char *)odp);
  253.     }
  254. }
  255.  
  256. /* 
  257.  * For OS/2, we need to know if we have to convert to lower case.  This
  258.  * only applies to non-HPFS (FAT, NETWARE etc) file systems.
  259.  */
  260.  
  261. #ifdef OS2
  262. bool        IsHPFSFileSystem (char *directory)
  263. {
  264.     USHORT    nDrive;
  265.     ULONG    lMap;
  266.     BYTE    bData[64];
  267.     BYTE    bName[3];
  268.     USHORT    cbData;
  269.  
  270.     if ( _osmode == DOS_MODE )
  271.     return FALSE;
  272.  
  273. /*
  274.  * Mike tells me there are IFS calls to determine this, but he carn't
  275.  * remember which.  So we read the partition info and check for HPFS.
  276.  */
  277.  
  278.     if (isalpha (directory[0]) && (directory[1] == ':'))
  279.     nDrive = toupper (directory[0]) - '@';
  280.  
  281.     else
  282.     DosQCurDisk (&nDrive, &lMap);
  283.  
  284. /* Set up the drive name */
  285.  
  286.     bName[0] = (char) (nDrive + '@');
  287.     bName[1] = ':';
  288.     bName[2] = 0;
  289.  
  290.     cbData = sizeof (bData);
  291.  
  292. /* Read the info, if we fail - assume non-HPFS */
  293.  
  294.     if (DosQFSAttach (bName, 0, FSAIL_QUERYNAME, bData, &cbData, 0L) )
  295.     return FALSE;
  296.  
  297.     else if (!strcmp (bData + (*((USHORT *) (bData + 2)) + 7), "HPFS"))
  298.     return TRUE;
  299.  
  300.     else
  301.     return FALSE;
  302. }
  303. #endif
  304.